package com.bcx.wind.workflow.spring;

import com.bcx.wind.workflow.access.AbstractAccess;
import com.bcx.wind.workflow.access.DbInit;
import com.bcx.wind.workflow.access.paging.PagingBuilder;
import com.bcx.wind.workflow.db.tran.WindTransactionManager;
import com.bcx.wind.workflow.db.util.WindDbRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;

/**
 * Spring 持久层执行器
 *
 * @author zhanglei
 */
public class SpringAccess extends AbstractAccess {

    private static final Logger LOGGER = LoggerFactory.getLogger(SpringAccess.class);

    /**
     * 数据源
     */
    private DataSource dataSource;

    /**
     * spring jdbcTemplate
     */
    private JdbcTemplate jdbcTemplate;

    /**
     * 初始化数据库表使用
     */
    private final WindDbRunner runner = new WindDbRunner();

    public  SpringAccess(DataSource dataSource){
        this.dataSource = dataSource;
        this.jdbcTemplate = new JdbcTemplate(dataSource);
        this.paging = PagingBuilder.buildPaging(getConnection());
        this.initDB(getConnection());
    }


    /**
     * 初始化数据库
     * @param connection   连接
     */
    private void initDB(Connection connection){
        try {
            String initSql = DbInit.getDbSql(connection);
            this.runner.saveOrUpdate(connection,initSql);
        }catch (Exception e){
            e.printStackTrace();
        }
        WindTransactionManager.getInstance().commit();
    }

    @Override
    protected int saveOrUpdate(String sql, Object[] args) {
        if(LOGGER.isDebugEnabled()){
            LOGGER.debug(" run sql: "+sql+" params: "+ Arrays.asList(args));
        }
        int ret =  this.jdbcTemplate.update(sql,args);
        if(LOGGER.isDebugEnabled()){
            LOGGER.debug("run success! result: "+ret);
        }
        return ret;
    }

    @Override
    protected <T> List<T> query(String sql, Object[] args, Class<T> clazz) {
        if(LOGGER.isDebugEnabled()){
            LOGGER.debug(" run sql: "+sql+" params: "+ Arrays.asList(args));
        }
        List<T> result =   jdbcTemplate.query(sql,new BeanPropertyRowMapper<>(clazz),args);
        if(LOGGER.isDebugEnabled()){
            LOGGER.debug("run success! result count: "+result.size());
        }
        return result;
    }

    @Override
    protected <T> T queryOne(String sql, Object[] args, Class<T> clazz) {
        List<T> result = query(sql,args,clazz);
        if(result.size() > 1){
            if(LOGGER.isDebugEnabled()){
                LOGGER.debug("queryOne operate back result total is more! ");
            }
        }

        return result.get(0);
    }

    @Override
    protected Object queryObject(String sql, Object[] args){
        if(LOGGER.isDebugEnabled()){
            LOGGER.debug(" run sql: "+sql+" params: "+ Arrays.asList(args));
        }
        return jdbcTemplate.queryForObject(sql,args,Object.class);
    }

    @Override
    public long count(String sql, Object[] args) {
        if(LOGGER.isDebugEnabled()){
            LOGGER.debug(" run sql: "+sql+" params: "+ Arrays.asList(args));
        }
        return jdbcTemplate.queryForObject(sql,args,Integer.class);
    }

    @Override
    public synchronized Connection getConnection() {
        try {
            Connection connection =   this.jdbcTemplate.getDataSource().getConnection();
            WindTransactionManager.getInstance().setConnection(connection);
            return connection;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
}
